using System;
using System.Collections.Generic;
using System.Text;
using Forecast.Database;
using NUnit.Framework;

namespace Forecast.Business.Test
{
    [TestFixture]
    public class TestEndPrediction
    {
        #region Variables

        private EndPrediction _endPrediction;
        private Prediction _prediction;
        private IList<Player> _players;
        private IList<Holding> _holdings;
        private IList<Offer> _offers;
        private IList<Medal> _medals;

        #endregion
        #region Setup / Teardown

        [SetUp]
        public void Init()
        {
            _endPrediction = new EndPrediction();
            _prediction = Mocks.GetPrediction();
            _players = Mocks.GetAllPlayers();
            _holdings = Mocks.GetAllHoldingsForOnePrediction();
            _medals = Mocks.GetAllMedals();
            InitOffers();
        }

        private void InitOffers()
        {
           _offers = new List<Offer>();

            Offer offer = new Offer();
            offer.AcceptorId = _players[0].Id;
            offer.EndDate = DateTime.Today.AddDays(-10);
            offer.Id = 75;
            offer.IsAccepted = true;
            offer.IsActive = false;
            offer.IsBuy = true;
            offer.NumPredictions = 5;
            offer.PlayerId = _players[1].Id;
            offer.PredictionId = MockIds.PREDICTION;
            offer.Price = 60;
            _offers.Add(offer);

            offer = new Offer();
            offer.AcceptorId = _players[3].Id;
            offer.EndDate = DateTime.Today.AddDays(-9);
            offer.Id = 76;
            offer.IsAccepted = true;
            offer.IsActive = false;
            offer.IsBuy = false;
            offer.NumPredictions = 5;
            offer.PlayerId = _players[0].Id;
            offer.PredictionId = MockIds.PREDICTION;
            offer.Price = 50;
            _offers.Add(offer);

            offer = new Offer();
            offer.AcceptorId = _players[3].Id;
            offer.EndDate = DateTime.Today.AddDays(-8);
            offer.Id = 77;
            offer.IsAccepted = true;
            offer.IsActive = false;
            offer.IsBuy = false;
            offer.NumPredictions = 5;
            offer.PlayerId = _players[0].Id;
            offer.PredictionId = MockIds.PREDICTION;
            offer.Price = 45;
            _offers.Add(offer);

            offer = new Offer();
            offer.AcceptorId = _players[0].Id;
            offer.EndDate = DateTime.Today.AddDays(-7);
            offer.Id = 78;
            offer.IsAccepted = true;
            offer.IsActive = false;
            offer.IsBuy = true;
            offer.NumPredictions = 5;
            offer.PlayerId = _players[2].Id;
            offer.PredictionId = MockIds.PREDICTION;
            offer.Price = 40;
            _offers.Add(offer);

            offer = new Offer();
            offer.AcceptorId = _players[0].Id;
            offer.EndDate = DateTime.Today.AddDays(-6);
            offer.Id = 79;
            offer.IsAccepted = true;
            offer.IsActive = false;
            offer.IsBuy = true;
            offer.NumPredictions = 15;
            offer.PlayerId = _players[3].Id;
            offer.PredictionId = MockIds.PREDICTION;
            offer.Price = 40;
            _offers.Add(offer);

            offer = new Offer();
            offer.AcceptorId = _players[2].Id;
            offer.EndDate = DateTime.Today.AddDays(-5);
            offer.Id = 80;
            offer.IsAccepted = true;
            offer.IsActive = false;
            offer.IsBuy = false;
            offer.NumPredictions = 20;
            offer.PlayerId = _players[1].Id;
            offer.PredictionId = MockIds.PREDICTION;
            offer.Price = 35;
            _offers.Add(offer);

            offer = new Offer();
            offer.AcceptorId = _players[3].Id;
            offer.EndDate = DateTime.Today.AddDays(-4);
            offer.Id = 81;
            offer.IsAccepted = true;
            offer.IsActive = false;
            offer.IsBuy = false;
            offer.NumPredictions = 15;
            offer.PlayerId = _players[1].Id;
            offer.PredictionId = MockIds.PREDICTION;
            offer.Price = 35;
            _offers.Add(offer);

            offer = new Offer();
            offer.AcceptorId = 0;
            offer.EndDate = DateTime.Today.AddDays(3);
            offer.Id = 82;
            offer.IsAccepted = false;
            offer.IsActive = true;
            offer.IsBuy = true;
            offer.NumPredictions = 60;
            offer.PlayerId = _players[3].Id;
            offer.PredictionId = MockIds.PREDICTION;
            offer.Price = 25;
            _offers.Add(offer);
        }

        #endregion
        #region Tests

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void NullPrediction()
        {
            _endPrediction.Execute(null, _players, _holdings, _offers, _medals, true);
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void NullPlayers()
        {
            _endPrediction.Execute(_prediction, null, _holdings, _offers, _medals, true);
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void NullHoldings()
        {
            _endPrediction.Execute(_prediction, _players, null, _offers, _medals, true);
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void NullMedals()
        {
            _endPrediction.Execute(_prediction, _players, _holdings, _offers, null, true);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void NullOnePlayer()
        {
            _players.Add(null);
            _endPrediction.Execute(_prediction, _players, _holdings, _offers, _medals, true);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void NullOneHolding()
        {
            _holdings.Add(null);
            _endPrediction.Execute(_prediction, _players, _holdings, _offers, _medals, true);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void NullOneOffer()
        {
            _offers.Add(null);
            _endPrediction.Execute(_prediction, _players, _holdings, _offers, _medals, true);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void NullOneMedal()
        {
            _medals.Add(null);
            _endPrediction.Execute(_prediction, _players, _holdings, _offers, _medals, true);
        }

        [Test]
        public void PredictionSetToInactive()
        {
            _endPrediction.Execute(_prediction, _players, _holdings, _offers, _medals, true);
            Assert.LessOrEqual(DateTime.Today, _endPrediction.EndPredictionPrediction.EndDate);
            Assert.AreEqual(false, _endPrediction.EndPredictionPrediction.IsActive);
            Assert.AreEqual(true, _endPrediction.EndPredictionPrediction.IsClosed);
        }

        [Test]
        public void PlayersCashUpdatedUponSuccessfulPrediction()
        {
            _endPrediction.Execute(_prediction, _players, _holdings, _offers, _medals, true);
            Assert.AreEqual(2000, _endPrediction.EndPredictionPlayers[0].Cash);
            Assert.AreEqual(2500, _endPrediction.EndPredictionPlayers[1].Cash);
            Assert.AreEqual(8000, _endPrediction.EndPredictionPlayers[2].Cash);
            Assert.AreEqual(11500, _endPrediction.EndPredictionPlayers[3].Cash);
        }

        [Test]
        public void PlayersCashUpdatedUponUnsuccessfulPrediction()
        {
            _endPrediction.Execute(_prediction, _players, _holdings, _offers, _medals, false);
            Assert.AreEqual(500, _endPrediction.EndPredictionPlayers[0].Cash);
            Assert.AreEqual(500, _endPrediction.EndPredictionPlayers[1].Cash);
            Assert.AreEqual(500, _endPrediction.EndPredictionPlayers[2].Cash);
            Assert.AreEqual(2500, _endPrediction.EndPredictionPlayers[3].Cash);
        }

        [Test]
        public void MedalReceivedForUnSuccessfulPrediction()
        {
            _endPrediction.Execute(_prediction, _players, _holdings, _offers, _medals, false);            
            Assert.AreEqual(MockIds.MEDAL_FATALUM, _endPrediction.EndPredictionPredictionResults[0].MedalId);
            Assert.AreEqual(MockIds.MEDAL_NONE, _endPrediction.EndPredictionPredictionResults[1].MedalId);
            Assert.AreEqual(MockIds.MEDAL_NONE, _endPrediction.EndPredictionPredictionResults[2].MedalId);
            Assert.AreEqual(MockIds.MEDAL_NONE, _endPrediction.EndPredictionPredictionResults[3].MedalId);
        }

        [Test]
        public void MedalReceivedForSuccessfulPrediction()
        {
            _endPrediction.Execute(_prediction, _players, _holdings, _offers, _medals, true);
            Assert.AreEqual(MockIds.MEDAL_NONE, _endPrediction.EndPredictionPredictionResults[0].MedalId);
            Assert.AreEqual(MockIds.MEDAL_NONE, _endPrediction.EndPredictionPredictionResults[1].MedalId);
            Assert.AreEqual(MockIds.MEDAL_NONE, _endPrediction.EndPredictionPredictionResults[2].MedalId);
            Assert.AreEqual(MockIds.MEDAL_PREDICTUM, _endPrediction.EndPredictionPredictionResults[3].MedalId);
        }

        [Test]
        public void NewsItemsCreated()
        {
            _endPrediction.Execute(_prediction, _players, _holdings, _offers, _medals, true);
            Assert.Greater(_endPrediction.EndPredictionNewsItems.Count, 0);
        }

        [Test]
        public void PredictionResultsCalculation()
        {
            _endPrediction.Execute(_prediction, _players, _holdings, _offers, _medals, false);
            Assert.AreEqual(1575, _endPrediction.EndPredictionPredictionResults[0].CashEarned);
            Assert.AreEqual(925, _endPrediction.EndPredictionPredictionResults[1].CashEarned);
            Assert.AreEqual(-900, _endPrediction.EndPredictionPredictionResults[2].CashEarned);
            Assert.AreEqual(-1600, _endPrediction.EndPredictionPredictionResults[3].CashEarned);
        }

        [Test]
        public void NoMedalsReceivedIfInactive()
        {
            _offers.Clear();
            _endPrediction.Execute(_prediction, _players, _holdings, _offers, _medals, true);
            Assert.AreEqual(MockIds.MEDAL_NONE, _endPrediction.EndPredictionPredictionResults[0].MedalId);
            Assert.AreEqual(MockIds.MEDAL_NONE, _endPrediction.EndPredictionPredictionResults[1].MedalId);
            Assert.AreEqual(MockIds.MEDAL_NONE, _endPrediction.EndPredictionPredictionResults[2].MedalId);
            Assert.AreEqual(MockIds.MEDAL_NONE, _endPrediction.EndPredictionPredictionResults[3].MedalId);
        }

        #endregion
    }
}
